package cn.like.common.excel;


import cn.hutool.json.JSONUtil;
import cn.like.base.support.result.Rest;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Set;

/**
 * 官网 https://www.yuque.com/easyexcel/doc/easyexcel
 *
 * @author <a href="mailto:likelovec@gmail.com">like</a>
 * @date 2021/7/19 10:50
 */
public class Excel {

    /**
     * 读取excel文件
     *
     * @param fileName          excel文件路径 like:  String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
     * @param type              excel文件中数据的类型
     * @param baseExcelListener excel侦听器
     */
    public static void readFromExcel(String fileName, Class type, BaseExcelListener baseExcelListener) {
        ExcelReader excelReader = null;
        try {
            excelReader = EasyExcel.read(fileName, type, baseExcelListener).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).build();
            excelReader.read(readSheet);
        } finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭，读的时候会创建临时文件，到时磁盘会崩的
                excelReader.finish();
            }
        }

    }

    /**
     * 读取excel文件
     *
     * @param file              excel文件
     * @param type              excel文件数据类型
     * @param baseExcelListener excel侦听器
     */
    public static void readFromExcelFile(File file, Class type, BaseExcelListener baseExcelListener) {
        ExcelReader excelReader = null;
        try {
            excelReader = EasyExcel.read(file, type, baseExcelListener).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).build();
            excelReader.read(readSheet);
        } finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭，读的时候会创建临时文件，到时磁盘会崩的
                excelReader.finish();
            }
        }
    }

    /**
     * 写入excel
     *
     * @param fileName                文件名称    fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
     * @param type                    需要写入的数据类型
     * @param dataList                数据列表
     * @param sheetName               sheet的名字
     * @param includeColumnFiledNames 需要写入的字段
     */
    public static void writeToExcel(String fileName, Class type, List dataList, String sheetName, Set<String> includeColumnFiledNames) {
        // 这里 需要指定写用哪个class去写
        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcel.write(fileName, type).includeColumnFiledNames(includeColumnFiledNames).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
            excelWriter.write(dataList, writeSheet);
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    /**
     * @see cn.like.common.excel.Excel#writeToExcel(String, Class, java.util.List, String, java.util.Set)
     */
    public static void writeToExcel(String fileName, Class type, List dataList, Set<String> includeColumnFiledNames) {
        Excel.writeToExcel(fileName, type, dataList, "sheet1", includeColumnFiledNames);
    }

    /**
     * @see cn.like.common.excel.Excel#writeToExcel(String, Class, java.util.List, String, java.util.Set)
     */
    public static void writeToExcel(String fileName, Class type, List dataList, String sheetName) {
        Excel.writeToExcel(fileName, type, dataList, sheetName, null);
    }

    /**
     * @see cn.like.common.excel.Excel#writeToExcel(String, Class, java.util.List, String, java.util.Set)
     */
    public static void writeToExcel(String fileName, Class type, List dataList) {
        Excel.writeToExcel(fileName, type, dataList, "sheet1");
    }

    /**
     * 写到web
     *
     * @param response                http response
     * @param fileName                文件名称（不带.xlsx后缀）
     * @param type                    要写入的文件的数据类型
     * @param dataList                数据列表
     * @param sheetName               sheet name
     * @param includeColumnFiledNames 需要写入的字段
     * @throws IOException ioexception
     */
    public static void writeToResponse(HttpServletResponse response, String fileName, Class type, List dataList, String sheetName, Set<String> includeColumnFiledNames) throws IOException {
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String realFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), type)
                    .includeColumnFiledNames(includeColumnFiledNames)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet(sheetName)
                    .doWrite(dataList);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().println(JSONUtil.toJsonStr(Rest.failed("下载文件失败")));
            response.getWriter().close();
        }
    }

    /**
     * @see cn.like.common.excel.Excel#writeToExcel(String, Class, java.util.List, String, java.util.Set)
     */
    public static void writeToResponse(HttpServletResponse response, String fileName, Class type, List dataList, Set<String> includeColumnFiledNames) throws IOException {
        Excel.writeToResponse(response, fileName, type, dataList, "sheet1", includeColumnFiledNames);
    }

    /**
     * @see cn.like.common.excel.Excel#writeToExcel(String, Class, java.util.List, String, java.util.Set)
     */
    public static void writeToResponse(HttpServletResponse response, String fileName, Class type, List dataList, String sheetName) throws IOException {
        Excel.writeToResponse(response, fileName, type, dataList, sheetName, null);
    }

    /**
     * @see cn.like.common.excel.Excel#writeToExcel(String, Class, java.util.List, String, java.util.Set)
     */
    public static void writeToResponse(HttpServletResponse response, String fileName, Class type, List dataList) throws IOException {
        Excel.writeToResponse(response, fileName, type, dataList, "sheet1");
    }


    // write demo
    //    public static void main(String[] args) {
    //        List<DemoData> dataList = new ArrayList<>();
    //        for (int i = 1; i < 1000000; i++) {
    //            final DemoData demoData = new DemoData();
    //            demoData.setString("第" + i + "- 标题 ");
    //            demoData.setDate(new Date());
    //            demoData.setDoubleData((double) i);
    //
    //            dataList.add(demoData);
    //        }
    //        Excel.writeToExcel("demo.xlsx", DemoData.class, dataList);
    //    }
    //
    //    @Data
    //    class DemoData {
    //        @ExcelProperty("字符串标题")
    //        private String string;
    //        @ExcelProperty("日期标题")
    //        private Date date;
    //        @ExcelProperty("数字标题")
    //        private Double doubleData;
    //        /**
    //         * 忽略这个字段
    //         */
    //        @ExcelIgnore
    //        private String ignore;
    //    }

}

